#include <SDL.h>
#include <stdlib.h>

#include "sprite.h"
#include "direction.h"
#include "misc.h"
#include "view.h"
#include "control.h"

extern SDL_Renderer* g_renderer;

SDL_Texture* g_texture = NULL;
Sprite* g_sprites = NULL;
Sprite* g_cell_sprite = NULL;
Sprite* g_select_sprite = NULL;
Sprite* g_canmove_sprite = NULL;
Sprite* g_control_sprite = NULL;

void LoadFromFile(const char* fname) {
    SDL_Surface *bmp = SDL_LoadBMP(fname);
    SDL_SetColorKey(bmp, SDL_TRUE, 63);
    CheckRes("SDL_LoadBMP", bmp == NULL);

    InitCell(bmp);
    InitControl(bmp);

    g_texture = SDL_CreateTextureFromSurface(g_renderer, bmp);
    SDL_FreeSurface(bmp);

    CheckRes("SDL_CreateTextureFromSurface", g_texture == NULL);
}

void DrawSprite(Sprite* sprite, int x, int y) {
    SDL_Rect dst = {x + sprite->offset.x, y + sprite->offset.y, sprite->rect.w, sprite->rect.h };
    SDL_RenderCopyEx(g_renderer, sprite->texture, &sprite->rect, &dst,
            0, 0, sprite->flip);
}

void InitSprites() {
    SDL_Rect r_up           = {0, 0, 19, 39};
    SDL_Rect r_up_right     = {20, 0, 39, 39};
    SDL_Rect r_right        = {20, 40, 39, 39};
    SDL_Rect r_down_right   = {20, 80, 39, 39};
    SDL_Rect r_down         = {0, 80, 19, 39};

    SDL_Point o_up          = {28, -10};
    SDL_Point o_right       = {22, -12};


    g_sprites = calloc(DIR_MAX * 2 + 4, sizeof(Sprite));
    g_cell_sprite = g_sprites + DIR_MAX * 2;
    g_select_sprite = g_sprites + DIR_MAX * 2 + 1;
    g_canmove_sprite = g_sprites + DIR_MAX * 2 + 2;
    g_control_sprite = g_sprites + DIR_MAX * 2 + 3;

    if (!g_sprites) {
        exit(2);
    }

    LoadFromFile("res/hello.bmp");

    g_sprites[DIR_UP].texture = g_texture;
    g_sprites[DIR_UP].rect = r_up;
    g_sprites[DIR_UP].flip = SDL_FLIP_NONE;
    g_sprites[DIR_UP].offset = o_up;

    g_sprites[DIR_UP_RIGHT].texture = g_texture;
    g_sprites[DIR_UP_RIGHT].rect = r_up_right;
    g_sprites[DIR_UP_RIGHT].flip = SDL_FLIP_NONE;
    g_sprites[DIR_UP_RIGHT].offset = o_right;

    g_sprites[DIR_RIGHT].texture = g_texture;
    g_sprites[DIR_RIGHT].rect = r_right;
    g_sprites[DIR_RIGHT].flip = SDL_FLIP_NONE;
    g_sprites[DIR_RIGHT].offset = o_right;

    g_sprites[DIR_DOWN_RIGHT].texture = g_texture;
    g_sprites[DIR_DOWN_RIGHT].rect = r_down_right;
    g_sprites[DIR_DOWN_RIGHT].flip = SDL_FLIP_NONE;
    g_sprites[DIR_DOWN_RIGHT].offset = o_right;

    g_sprites[DIR_DOWN].texture = g_texture;
    g_sprites[DIR_DOWN].rect = r_down;
    g_sprites[DIR_DOWN].flip = SDL_FLIP_NONE;
    g_sprites[DIR_DOWN].offset = o_up;

    g_sprites[DIR_DOWN_LEFT] = g_sprites[DIR_DOWN_RIGHT];
    g_sprites[DIR_DOWN_LEFT].flip = SDL_FLIP_HORIZONTAL;

    g_sprites[DIR_LEFT] = g_sprites[DIR_RIGHT];
    g_sprites[DIR_LEFT].flip = SDL_FLIP_HORIZONTAL;

    g_sprites[DIR_UP_LEFT] = g_sprites[DIR_UP_RIGHT];
    g_sprites[DIR_UP_LEFT].flip = SDL_FLIP_HORIZONTAL;

    int i;
    for (i = 0; i < DIR_MAX; ++i) {
        g_sprites[DIR_MAX + i] = g_sprites[i];
        g_sprites[DIR_MAX + i].rect.y += 120;
    }

    SDL_Rect cell_rect = {60, 41, 76, 38};
    SDL_Point o_zero   = {0, 0};
    g_cell_sprite->texture = g_texture;
    g_cell_sprite->rect = cell_rect;
    g_cell_sprite->flip = SDL_FLIP_NONE;
    g_cell_sprite->offset = o_zero;

    SDL_Rect select_rect = {60, 80, 78, 39};
    SDL_Point o_select   = {-1, 0};
    g_select_sprite->texture = g_texture;
    g_select_sprite->rect = select_rect;
    g_select_sprite->flip = SDL_FLIP_NONE;
    g_select_sprite->offset = o_select;

    SDL_Rect canmove_rect = {62, 120, 73, 37};
    SDL_Point o_canmove   = {1, 1};
    g_canmove_sprite->texture = g_texture;
    g_canmove_sprite->rect = canmove_rect;
    g_canmove_sprite->flip = SDL_FLIP_NONE;
    g_canmove_sprite->offset = o_canmove;

    SDL_Rect control_rect = {0, 240, 140, 140};
    SDL_Point control_point   = {0, 0};
    g_control_sprite->texture = g_texture;
    g_control_sprite->rect = control_rect;
    g_control_sprite->flip = SDL_FLIP_NONE;
    g_control_sprite->offset = control_point;
}

void DestroySprites() {
    if (g_sprites)
        free(g_sprites);
    SDL_DestroyTexture(g_texture);
    DestroyCell();
}
